﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using System.Windows.Data;
using System.ComponentModel;
using EIA.Basic.Model;
using EIA.Basic.BLL.ClientProxy;
using System.Collections.ObjectModel;
using EIA.SLClient.Utility.Controls;

namespace EIA.SLClient.PlatManage.BasicMgr
{
    public class StaffEditViewModel : SimpleMvvmToolkit.ViewModelDetailBase<StaffEditViewModel, EIA.Basic.Model.TStaff>
    {
        public StaffEditViewModel()
        {
            IsShow = false;
            if (IsInDesignMode) IsShow = true;
            UserEditVM = new UserEditViewModel();

            this.RegisterToReceiveMessages<Tuple<TStaff, TUser>>(EIA.SLClient.PlatManage.Infrastructure.MessageTokens.STAFF_UPDATE, EP_Update);
            this.RegisterToReceiveMessages<Tuple<TStaff, TUser>>(EIA.SLClient.PlatManage.Infrastructure.MessageTokens.STAFF_NEW, EP_New);

            TryLoadPositions();
            TryLoadDepartments();
        }

        private void EP_Update(object sender, SimpleMvvmToolkit.NotificationEventArgs<Tuple<TStaff, TUser>> e)
        {
            TryLoadPositions();
            TryLoadDepartments();
            this.TitleTip = "修改";
            this.Model = e.Data.Item1;
            if (e.Data.Item1.IsActive != 0)
            {
                this.BeginEdit();
            }
            SelectPosition();
            SelectDepartment();
            this.UserEditVM.Model = e.Data.Item2;
            if (e.Data.Item1.IsActive != 0) this.UserEditVM.BeginEdit();
            this.IsShow = true;
            this.IsNew = false;
            SaveCommand.RaiseCanExecuteChanged();
        }

        private void EP_New(object sender, SimpleMvvmToolkit.NotificationEventArgs<Tuple<TStaff, TUser>> e)
        {
            TryLoadPositions();
            TryLoadDepartments();
            this.TitleTip = "添加";
            this.Model = e.Data.Item1;
            this.BeginEdit();
            SelectPosition();
            SelectDepartment();
            this.UserEditVM.Model = e.Data.Item2;
            this.UserEditVM.BeginEdit();
            this.IsShow = true;
            this.IsNew = true;
            SaveCommand.RaiseCanExecuteChanged();
        }

        private void Busy(string msg = "等待...")
        {
            IsBusy = true;
            SendMessage<bool>(EIA.SLClient.PlatManage.Infrastructure.MessageTokens.STAFF_BUSY_STATE, new SimpleMvvmToolkit.NotificationEventArgs<bool>(msg, true));
        }

        private void Free()
        {
            IsBusy = false;
            SendMessage<bool>(EIA.SLClient.PlatManage.Infrastructure.MessageTokens.STAFF_BUSY_STATE, new SimpleMvvmToolkit.NotificationEventArgs<bool>("", false));
        }

        #region notifyprop

        protected bool _IsBusy;
        /// <summary>
        /// 
        /// </summary>
        public bool IsBusy
        {
            get { return _IsBusy; }
            set
            {
                _IsBusy = value;
                NotifyPropertyChanged(m => m.IsBusy);
            }
        }

        protected string _TitleTip;
        /// <summary>
        /// 注释
        /// </summary>
        public string TitleTip
        {
            get { return _TitleTip; }
            set
            {
                _TitleTip = value;
                NotifyPropertyChanged(m => m.TitleTip);
            }
        }

        protected bool _IsShow;
        /// <summary>
        /// 是否显示
        /// </summary>
        public bool IsShow
        {
            get { return _IsShow; }
            set
            {
                _IsShow = value;
                NotifyPropertyChanged(m => m.IsShow);
            }
        }

        protected UserEditViewModel _UserEditVM;
        /// <summary>
        /// 注释
        /// </summary>
        public UserEditViewModel UserEditVM
        {
            get { return _UserEditVM; }
            set
            {
                _UserEditVM = value;
                NotifyPropertyChanged(m => m.UserEditVM);
            }
        }

        protected bool _IsNew;
        /// <summary>
        /// 是否为添加操作
        /// </summary>
        public bool IsNew
        {
            get { return _IsNew; }
            set
            {
                _IsNew = value;
                NotifyPropertyChanged(m => m.IsNew);
            }
        }

        protected System.Collections.ObjectModel.ObservableCollection<TPosition> _PositionCollection;
        /// <summary>
        /// 注释
        /// </summary>
        public System.Collections.ObjectModel.ObservableCollection<TPosition> PositionCollection
        {
            get { return _PositionCollection; }
            set
            {
                _PositionCollection = value;
                NotifyPropertyChanged(m => m.PositionCollection);
            }
        }

        protected TPosition _Position;
        /// <summary>
        /// 注释
        /// </summary>
        public TPosition Position
        {
            get { return _Position; }
            set
            {
                _Position = value;
                NotifyPropertyChanged(m => m.Position);
                UpdatePosition();
            }
        }

        protected ObservableCollection<TreeNode> _DepartmentRootNodes;
        public ObservableCollection<TreeNode> DepartmentRootNodes
        {
            get { return _DepartmentRootNodes; }
            set
            {
                _DepartmentRootNodes = value;
                NotifyPropertyChanged(m => m.DepartmentRootNodes);
            }
        }

        protected TDepartment _Department;
        /// <summary>
        /// 注释
        /// </summary>
        public TDepartment Department
        {
            get { return _Department; }
            set
            {
                _Department = value;
                NotifyPropertyChanged(m => m.Department);
                UpdateDepartment();
            }
        }


        #endregion

        #region command

        #region SaveCommand

        private SimpleMvvmToolkit.DelegateCommand _SaveCommand = null;
        public SimpleMvvmToolkit.DelegateCommand SaveCommand
        {
            get
            {
                if (_SaveCommand == null)
                {
                    _SaveCommand = new SimpleMvvmToolkit.DelegateCommand(Save, CanExcuteSave);
                } return _SaveCommand;
            }
            set { _SaveCommand = value; NotifyPropertyChanged(m => m.SaveCommand); }
        }

        public void Save()
        {
            EIA.Basic.BLL.ClientProxy.XStaffProxy proxy = new Basic.BLL.ClientProxy.XStaffProxy();
            Busy();
            if (IsNew) proxy.Insert(new Tuple<TStaff, TUser>(Model, UserEditVM.Model), (k) =>
            {
                Free();
                Model.StfId = k;
                UserEditVM.Model.StfId = k;
                this.EndEdit();
                this.UserEditVM.EndEdit();
                this.TitleTip = "";
                this.IsShow = false;
                this.Model = null;
                this.UserEditVM.Model = null;
            }, (ex) =>
            {
                Free();
                this.TitleTip = "添加 (发生错误)";
            });
            else proxy.Update(new Tuple<TStaff, TUser>(Model, UserEditVM.Model), (r) =>
            {
                Free();
                if (r)
                {
                    this.EndEdit();
                    this.UserEditVM.EndEdit();
                    this.TitleTip = "";
                    this.IsShow = false;
                    this.Model = null;
                    this.UserEditVM.Model = null;
                }
                else
                {
                    this.TitleTip = "修改 （数据库更新失败）";
                }
            }, (ex) =>
            {
                Free();
                this.TitleTip = "修改 （发生错误）";
            });
        }

        public bool CanExcuteSave()
        {
            return Model != null && Model.IsActive != 0;
        }

        #endregion

        #region CancelCommand

        private SimpleMvvmToolkit.DelegateCommand _CancelCommand = null;
        public SimpleMvvmToolkit.DelegateCommand CancelCommand
        {
            get
            {
                if (_CancelCommand == null)
                {
                    _CancelCommand = new SimpleMvvmToolkit.DelegateCommand(Cancel, CanExcuteCancel);
                } return _CancelCommand;
            }
            set { _CancelCommand = value; NotifyPropertyChanged(m => m.CancelCommand); }
        }

        public void Cancel()
        {
            this.CancelEdit();
            this.UserEditVM.CancelEdit();
            if (this.IsNew) SendMessage<Tuple<TStaff, TUser>>(EIA.SLClient.PlatManage.Infrastructure.MessageTokens.STAFF_NEW_CANCEL, new SimpleMvvmToolkit.NotificationEventArgs<Tuple<TStaff, TUser>>("", new Tuple<TStaff, TUser>(Model, UserEditVM.Model)));
            this.TitleTip = "";
            this.IsShow = false;
            this.Model = null;
            this.UserEditVM.Model = null;
            //if (this.IsNew) SendMessage(EIA.SLClient.PlatManage.Infrastructure.MessageTokens.STAFF_RETRIEVE, new SimpleMvvmToolkit.NotificationEventArgs());
        }

        public bool CanExcuteCancel()
        {
            return true;
        }

        #endregion

        #endregion

        public void TryLoadPositions()
        {
            if (PositionCollection == null)
            {
                LoadPositions();
            }
        }

        public void LoadPositions()
        {
            TPositionProxy proxy = new TPositionProxy();
            proxy.ListAll((lst) =>
            {
                PositionCollection = new System.Collections.ObjectModel.ObservableCollection<TPosition>(lst);
            });
        }

        public void TryLoadDepartments()
        {
            if (DepartmentRootNodes == null) LoadDepartments();
        }

        public void LoadDepartments()
        {
            EIA.Basic.BLL.ClientProxy.TDepartmentProxy proxy = new Basic.BLL.ClientProxy.TDepartmentProxy();

            proxy.ListAll((lst) =>
            {
                if (lst == null) return;
                int c = lst.Count;
                lst = new List<TDepartment>(lst.OrderBy((d) => { return d.OrderId == null ? c++ : d.OrderId.Value; }));
                ObservableCollection<TreeNode> root = new ObservableCollection<TreeNode>();
                Dictionary<int, TreeNode> dic = new Dictionary<int, TreeNode>();
                foreach (var d in lst)
                {
                    dic[d.DepId] = new TreeNode() { Text = d.DepName, Data = d };
                }
                foreach (var n in dic.Values)
                {
                    TDepartment d = n.Data as TDepartment;
                    if (d != null && d.SupId.HasValue) dic[d.SupId.Value].Children.Add(n);
                    else root.Add(n);
                }
                DepartmentRootNodes = root;
            }, (ex) =>
            {
            });
        }

        private void SelectDepartment()
        {
            TreeNode node = TreeNode.FindNode(DepartmentRootNodes, (o) =>
            {
                TDepartment d = o as TDepartment;
                if (d != null && d.DepId == Model.DepId)
                {
                    return true;
                }
                return false;
            });

            this.Department = node == null ? null : node.Data as TDepartment;
        }

        private void SelectPosition()
        {
            if (Model.PosId == null) Position = null;
            Position = PositionCollection.FirstOrDefault((p) => { return p.PosId == Model.PosId; });
        }

        private void UpdateDepartment()
        {
            this.Model.DepId = Department == null ? null : (int?)Department.DepId;
            this.Model.DepName = Department == null ? null : Department.DepName;
        }

        private void UpdatePosition()
        {
            this.Model.PosId = Position == null ? null : (int?)Position.PosId;
            this.Model.PosName = Position == null ? null : Position.PosName;
            this.Model.PosLevel = Position == null ? null : (int?)Position.PosLevel;
        }
    }
}